using Microsoft.Extensions.DependencyInjection;

namespace YMJake.Flowable.ExternalWorker.Client.AspNetCore.Pipeline;

/// <summary>
/// Implementation of worker pipeline
/// </summary>
public class WorkerPipeline : IWorkerPipeline
{
    private readonly List<WorkerMiddlewareFactory> _middlewares = new();
    private readonly List<Type> _handlerTypes = new();

    public IWorkerPipeline Use(WorkerMiddlewareFactory middleware)
    {
        _middlewares.Add(middleware ?? throw new ArgumentNullException(nameof(middleware)));
        return this;
    }

    public IWorkerPipeline AddHandler<THandler>() where THandler : class, IWorkerHandler
    {
        _handlerTypes.Add(typeof(THandler));
        return this;
    }

    public WorkerMiddleware Build()
    {
        // Build the core handler pipeline
        WorkerMiddleware pipeline = async context =>
        {
            foreach (var handlerType in _handlerTypes)
            {
                var handler = (IWorkerHandler)context.ServiceProvider.GetRequiredService(handlerType);
                await handler.HandleAsync(context);
                
                // If a result was set, stop processing
                if (context.Result != null)
                    break;
            }
        };

        // Apply middleware in reverse order
        for (int i = _middlewares.Count - 1; i >= 0; i--)
        {
            pipeline = _middlewares[i](pipeline);
        }

        return pipeline;
    }
}